# SpringBoot 源码分析
作者:Ethan.Yang
博客:https://blog.ethanyang.cn (opens new window)
# 自动装配
# @SpringBootApplication
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
注解解析
@SpringBootConfiguration- 声明当前类是 Spring 配置类,本质上是
@Configuration的特化。
- 声明当前类是 Spring 配置类,本质上是
@EnableAutoConfiguration- Spring Boot 自动装配的核心注解,负责启动自动装配逻辑。
@ComponentScan- 开启包扫描,默认扫描启动类所在包及子包下的组件:
@Component、@Service、@Controller、@Repository@Configuration配置类
- 可通过
excludeFilters排除不需要扫描的类。
- 开启包扫描,默认扫描启动类所在包及子包下的组件:
# @EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
1
2
3
4
5
6
7
2
3
4
5
6
7
核心作用
- 将
AutoConfigurationImportSelector注入 Spring IOC 容器 - 为后续自动装配提供入口,确定要导入的自动配置类
# AutoConfigurationImportSelector
关注 selectImports() 方法,它是 Spring Boot 自动装配的核心入口。
@Import(AutoConfigurationImportSelector) 触发
↓
调用 selectImports() 方法
↓
判断是否启用自动配置 isEnabled()
├─ 若关闭 → 返回空数组
└─ 若开启 → 执行 getAutoConfigurationEntry()
↓
解析 @EnableAutoConfiguration 注解参数
└─ 处理 exclude、excludeName 等排除配置
↓
加载候选自动配置类 getCandidateConfigurations()
├─ Spring Boot 2.x 及以前:读取 META-INF/spring.factories
└─ Spring Boot 3.x:读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
↓
去重 removeDuplicates() // 避免重复注册
↓
解析并校验排除项 getExclusions() & checkExcludedClasses()
↓
应用 AutoConfigurationImportFilter
└─ 根据 @ConditionalOnClass、@ConditionalOnBean 等条件过滤不满足的配置
↓
发布 AutoConfigurationImportEvent(事件通知机制)
↓
封装为 AutoConfigurationEntry 对象
↓
selectImports() 返回最终自动配置类全限定名数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
理解
selectImports()只负责确定哪些配置类需要注册,真正的 Bean 实例化还没有发生。- 其中
@Conditional系列注解, 也在此处进行过滤, 最终返回的是需要注册的所有配置。 - 这个数组的每一个类,最终都会在容器刷新阶段递归注册成 BeanDefinition。
Spring Boot 动态装配触发与注册流程
无论是通过 @Import(xxxImportSelector),还是通过 BeanDefinitionRegistryPostProcessor 注册 Bean,最终都依赖于 Spring IOC 容器刷新流程中的 invokeBeanFactoryPostProcessors(beanFactory)。
refresh() 容器刷新阶段
↓
invokeBeanFactoryPostProcessors(beanFactory)
└─ 容器刷新入口,触发所有 BeanFactoryPostProcessor
↓
invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
└─ 获取当前注册的 BeanFactoryPostProcessor 列表
↓
分类执行 BeanDefinitionRegistryPostProcessor(可注册新 BeanDefinition)与普通 BeanFactoryPostProcessor
↓
registryProcessors.forEach(postProcessor -> postProcessor.postProcessBeanFactory(beanFactory))
└─ 核心:ConfigurationClassPostProcessor 被调用,触发动态装配
↓
ConfigurationClassPostProcessor.postProcessBeanFactory(beanFactory)
└─ 解析 @Configuration 类、@Import 注解、@Bean 方法等
↓
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory)
└─ 遍历候选配置类,生成 ConfigurationClass 对象
↓
parser.parse(candidates)
└─ 扫描 @Configuration、@Component、@Import 等注解,递归解析
↓
deferredImportSelectorHandler.process()
└─ 处理 DeferredImportSelector(延迟导入模块),按分组顺序注册自动配置
↓
handler.processGroupImports()
└─ 遍历 DeferredImportSelector 分组,递归调用 processImports()
↓
processImports(
configurationClass,
asSourceClass(configurationClass, exclusionFilter),
Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
exclusionFilter,
false
)
└─ 递归解析 @Import 的配置类,生成 ConfigurationClass
↓
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata())
└─ AutoConfigurationImportSelector 获取自动配置类全限定名
↓
asSourceClasses(importClassNames, exclusionFilter)
└─ 转换为 SourceClass 对象,便于递归解析
↓
递归 processImports() → 每个配置类生成 ConfigurationClass 对象
↓
ConfigurationClassBeanDefinitionReader.registerBeanDefinitions()
└─ 注册配置类及其 @Bean 方法对应的 BeanDefinition
↓
BeanDefinition 注册完成,等待容器刷新实例化
↓
finishBeanFactoryInitialization() → 实例化 Bean
└─ Bean 被创建并注入依赖,自动装配完成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
理解
- 触发点
invokeBeanFactoryPostProcessors()是动态装配真正的入口- 核心处理器是
ConfigurationClassPostProcessor,负责扫描配置类和 @Import
- selectImports 的作用
- 它只负责返回配置类全限定名,不涉及实例化
- 递归注册 BeanDefinition 才是自动装配的核心
- 递归机制
processImports()会递归处理 @Import 和 DeferredImportSelector- 确保所有自动配置类和依赖类都被注册到 IOC 容器
- BeanDefinition 注册 vs 实例化
- 注册阶段:生成 BeanDefinition(配置类 + @Bean 方法)
- 实例化阶段:refresh() → finishBeanFactoryInitialization() → 创建 Bean 实例
- 只有实例化后,自动装配才真正生效
- 自动装配“自动”原因
- spring.factories 或 imports 文件记录了大量 AutoConfiguration 类
- ImportSelector 自动导入 → 递归注册 BeanDefinition → 容器刷新实例化 → 自动装配完成
- 条件注解(@ConditionalOnClass、@ConditionalOnBean 等)确保只装配满足条件的 Bean
# 启动依赖
在理解了 自动装配 的机制后,启动依赖就很好理解了:
- 启动依赖 = Starter
- 本质上是一个 jar 包,封装了一组功能依赖和约定的配置。
- 用户在项目中引入这个依赖,相当于告诉 Spring Boot:“我想使用这个功能模块。”
- 自动装配 = 动作 / 机制
- 自动装配负责 根据类路径、条件注解以及 SPI 配置,将 Starter 中声明的 Bean 自动注册到当前项目的 IOC 容器中。
- 换句话说,Starter 提供“入口”,自动装配完成“装载和生效”。
- 类比理解:
- Starter 就像一份工具箱,里面装着各种工具(依赖和配置)。
- 自动装配 就像工厂里的机器人,根据工具箱里的工具,自动把它们装配到你的项目中去使用。
可以参考 笔者Starter 示例 (opens new window) 来实现自己的
Spring Boot Starter。
# Actuator 监控
Spring Boot Actuator 提供生产级监控与管理功能,常用功能包括:
- 健康检查(Health)
- 应用指标(Metrics)
- 应用信息(Info)
- 日志管理(Loggers)
- 环境信息(Env / ConfigProps)
# 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
1
2
3
4
2
3
4
# 配置示例
management:
endpoints:
web:
exposure:
include: health, info, metrics, beans
endpoint:
health:
show-details: always
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
include:指定要暴露的 endpointsshow-details:显示完整健康信息
访问示例:
http://localhost:8080/actuator/health
http://localhost:8080/actuator/metrics
http://localhost:8080/actuator/beans
1
2
3
2
3
Actuator 本质上是依赖 Spring Boot 自动装配机制动态注册 Bean,使用时无需手动配置 Bean 即可生效。
大多数生产项目都有第三方监视工具, 如 Prometheus(监控) + Grafana(可视化工具), 后面会有专栏进行讲解。